Skip to content

evals: contains_expected / word_overlap raise on empty or whitespace expected#134

Merged
renaudcepre merged 1 commit into
mainfrom
fix-empty-expected-vacuous
Jun 24, 2026
Merged

evals: contains_expected / word_overlap raise on empty or whitespace expected#134
renaudcepre merged 1 commit into
mainfrom
fix-empty-expected-vacuous

Conversation

@renaudcepre

Copy link
Copy Markdown
Owner

What

Closes #126.

PR #123 made contains_expected and word_overlap raise when expected_output is None, but the empty-string frontier kept the old vacuous behavior:

  • contains_expected with expected="": "" in output is true for any output, so every case passes regardless of the result.
  • word_overlap with expected="" or whitespace-only: expected_words is empty and it returned a fabricated overlap=1.0, poisoning the tracked metric.

Both are the same silent-pass family as #116/#117/#118 — a result with no meaning that still comes back green. expected="" technically satisfied "requires expected" while still being vacuous.

Decision

Per discussion: fail-loud, consistent with #123 and the #116-118 family. The guard fires on the value that is actually vacuous for each evaluator:

  • contains_expected: raises when expected is empty or whitespace-only (empty after strip()).
  • word_overlap: raises when expected has no words after split() (empty or whitespace-only).

Each raises a clear ValueError naming the case and pointing at the fix (set a non-empty expected, or attach the evaluator per-case for mixed case sets). None keeps its existing dedicated message.

Tests

tests/evals/test_e2e.py (next to the existing *_none_expected_raises tests): empty and whitespace-only expected now raise, for both evaluators. Docs (docs/evals.md) updated to state the non-empty requirement.

Full suite: 1245 passed, ruff clean, mypy --strict clean.


Generated by Claude Code

…expected

PR #123 made both raise when expected_output is None, but the empty-string
frontier kept the old vacuous behavior:

- contains_expected with expected="": "" in output is true for any output,
  so every case passes.
- word_overlap with empty or whitespace-only expected: expected_words is
  empty and it returned a fabricated overlap=1.0.

Both are the same silent-pass family as #116/#117/#118: a result with no
meaning that still comes back green. Extend the None guard to empty and
whitespace-only expected (contains_expected: empty after strip; word_overlap:
no words after split), with a clear per-case error. Docs updated.

Closes #126
@renaudcepre
renaudcepre merged commit e0b4f1b into main Jun 24, 2026
11 checks passed
@renaudcepre
renaudcepre deleted the fix-empty-expected-vacuous branch June 24, 2026 20:08
renaudcepre added a commit that referenced this pull request Jun 25, 2026
…expected (#134)

PR #123 made both raise when expected_output is None, but the empty-string
frontier kept the old vacuous behavior:

- contains_expected with expected="": "" in output is true for any output,
  so every case passes.
- word_overlap with empty or whitespace-only expected: expected_words is
  empty and it returned a fabricated overlap=1.0.

Both are the same silent-pass family as #116/#117/#118: a result with no
meaning that still comes back green. Extend the None guard to empty and
whitespace-only expected (contains_expected: empty after strip; word_overlap:
no words after split), with a clear per-case error. Docs updated.

Closes #126

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

evals: contains_expected / word_overlap still vacuous on empty or whitespace-only expected

2 participants